home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 2: Applications
/
Linux Cubed Series 2 - Applications.iso
/
circuits
/
irsim-9.000
/
irsim-9
/
calibrate
/
findr.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-04-08
|
9KB
|
427 lines
#include <stdio.h>
#include <ctype.h>
typedef struct
{
char *name;
double *vals;
double hl_t;
double lh_t;
double tphl;
double tplh;
} Signal;
struct
{
int nv;
int np;
Signal *sigs;
} plot;
typedef struct
{
double w, l;
} TranSz;
double midpoint;
Signal *timev, *in1, *in2, *in3, *out1, *out2, *out3, *out4;
main( argc, argv )
int argc;
char *argv[];
{
FILE *fi = stdin;
TranSz p, n;
double cap;
int i;
cap = p.w = p.l = n.w = n.l = -1;
for( i = 1; i < argc; i++ )
{
if( argv[i][0] == '-' )
{
switch( argv[i][1] )
{
case 'c' :
i++;
if( i >= argc ) usage( "missing argument :" );
if( sscanf( argv[i], "%lf", &cap ) != 1 || cap <= 0 )
usage( "bad argument for 'c': " );
cap *= 1E-15; /* convert to ff */
break;
case 'n' :
i++;
if( i >= argc ) usage( "missing argument :" );
if( sscanf( argv[i], "%lf,%lf", &n.w, &n.l ) != 2 ||
n.w <= 0 || n.l <= 0 )
usage( "bad argument for 'n': " );
break;
case 'p' :
i++;
if( i >= argc ) usage( "missing argument :" );
if( sscanf( argv[i], "%lf,%lf", &p.w, &p.l ) != 2 ||
p.w <= 0 || p.l <= 0 )
usage( "bad argument for 'p': " );
break;
default :
usage( "unknown switch :" );
}
}
else
{
if( (fi = fopen( argv[i], "r" )) == NULL )
usage( "can not open input file :" );
}
}
if( cap <= 0 || n.l <= 0 || n.w <= 0 || p.l <= 0 || p.w <= 0 )
usage( "i am missing parameters:" );
if( read_header( fi ) == 0 )
exit( 1 );
if( read_variables( fi ) == 0 )
exit( 1 );
if( read_values( fi ) == 0 )
exit( 1 );
if( find_delays() == 0 )
exit( 1 );
PrintResistEntries( cap, &n, &p );
exit( 0 );
}
usage( s )
char *s;
{
fprintf( stderr, "%s\n", s );
fprintf( stderr, "usage: findr -c <cap> -nfet <w,l> -pfet <w,l> [rawfile]\n" );
fprintf( stderr, "\tcap -> loading capacitance (in fF)\n" );
fprintf( stderr, "\tw,l -> width, length of fet (in um)\n" );
fprintf( stderr, "\trawfile -> spice rawfile (ascii)\n" );
exit( 1 );
}
#define eqsubstr( VS, FS ) ( strncmp( (VS), FS, sizeof( FS ) -1 ) == 0 )
int read_header( f )
FILE *f;
{
char line[512];
int plotname = 0;
char *s;
while( fgets( line, 512, f ) )
{
if( eqsubstr( line, "Title:" ) )
;
else if( eqsubstr( line, "Date:" ) )
;
else if( eqsubstr( line, "Plotname:" ) )
plotname = 1;
else if( eqsubstr( line, "Flags:" ) )
;
else if( eqsubstr( line, "Command:" ) )
;
else if( eqsubstr( line, "No. Variables:" ) )
{
if( plotname == 0 )
{
fprintf( stderr, "missing Plotname entry\n" );
return( 0 );
}
for( s = line; *s != ':'; s++ );
s++;
if( sscanf( s, "%d", &plot.nv ) != 1 || plot.nv <= 0 )
{
fprintf( stderr, "bad line: %s", line );
return( 0 );
}
}
else if( eqsubstr( line, "No. Points:" ) )
{
if( plotname == 0 )
{
fprintf( stderr, "missing Plotname entry\n" );
return( 0 );
}
for( s = line; *s != ':'; s++ );
s++;
if( sscanf( s, "%d", &plot.np ) != 1 || plot.np <= 0 )
{
fprintf( stderr, "bad line: %s", line );
return( 0 );
}
}
else if( eqsubstr( line, "Variables:" ) )
{
if( plotname == 0 || plot.np == 0 | plot.nv == 0 )
{
fprintf( stderr, "missing entries:%s%s%s\n",
(plotname) ? "" : " 'Plotname'",
(plot.nv) ? "" : " 'No. Variables'",
(plot.np) ? "" : " 'No. Points'" );
}
return( 1 );
}
else
{
fprintf( stderr, "Unrecognized line: %s", line );
return( 0 );
}
}
fprintf( stderr, "premature EOF\n" );
return( 0 );
}
int read_variables( f )
FILE *f;
{
char line[200], name[100], type[100];
int i;
int ix;
double *v;
char *s, *p;
plot.sigs = (Signal *) calloc( plot.nv, sizeof( Signal ) );
if( plot.sigs == NULL )
{
fprintf( stderr, "no memory\n" );
return( 0 );
}
for( i = 0; i < plot.nv; i++ )
{
if( fgets( line, 200, f ) == NULL )
{
fprintf( stderr, "premature EOF\n" );
return( 0 );
}
if( sscanf( line, "%d %s %s", &ix, name, type ) != 3 )
{
fprintf( stderr, "bad 'variable' line: %s", line );
return( 0 );
}
s = (char *) malloc( strlen( name ) + 1 );
v = (double *) calloc( plot.np, sizeof( double ) );
if( v == NULL || s == NULL )
{
fprintf( stderr, "no memory\n" );
return( 0 );
}
plot.sigs[i].vals = v;
plot.sigs[i].name = s;
for( p = name; *p != '\0'; p++, s++ )
*s = ( isupper( *p ) ) ? tolower( *p ) : *p;
*s = '\0';
}
if( fgets( line, 100, f ) == NULL )
{
fprintf( stderr, "premature EOF\n" );
return( 0 );
}
if( eqsubstr( line, "Values:" ) )
return( 1 );
fprintf( stderr, "No 'Values' line\n" );
return( 0 );
}
int read_values( f )
FILE *f;
{
char line[200];
int n, i, n_p, z;
double v;
for( n = 0; n < plot.np; n++ )
{
if( fgets( line, 200, f ) == NULL )
{
fprintf( stderr, "premature EOF\n" );
return( 0 );
}
if( sscanf( line, "%d%lf", &n_p, &v ) != 2 || n_p != n )
{
fprintf( stderr, "bad 'value' line: %s", line );
return( 0 );
}
plot.sigs[0].vals[n] = v;
for( i = 1; i < plot.nv; i++ )
{
if( fgets( line, 200, f ) == NULL )
{
fprintf( stderr, "premature EOF\n" );
return( 0 );
}
if( sscanf( line, "%lf", &v ) != 1 )
{
fprintf( stderr, "bad 'value' line: %s", v, line );
return( 0 );
}
plot.sigs[i].vals[n] = v;
}
}
return( 1 );
}
Signal *find( name )
char *name;
{
int i;
Signal *sig;
for( i = 0, sig = plot.sigs; i < plot.nv; i++, sig++ )
{
if( strcmp( name, sig->name ) == 0 )
return( sig );
}
return( NULL );
}
double interp( y, v1, v2, t1, t2 )
double y, v1, v2, t1, t2;
{
return( t2 + (y - v2) * (t2 - t1) / (v2 - v1) );
}
#define L_H 1
#define H_L 2
#define BOTH ( L_H | H_L )
Signal *FindTransitions( name, which )
char *name;
int which;
{
Signal *sig;
double *v, *t;
int i;
if( (sig = find( name )) == NULL )
{
fprintf( stderr, "signal '%s' missing\n" );
return( NULL );
}
v = sig->vals;
t = timev->vals;
if( which & L_H )
{
for( i = 1; i < plot.np; i++ )
{
if( v[i-1] < midpoint && v[i] >= midpoint )
goto foundlh;
}
fprintf( stderr, "signal '%s' has no l->h transition\n", name );
return( NULL );
foundlh :
sig->lh_t = interp( midpoint, v[i-1], v[i], t[i-1], t[i] );
}
if( which & H_L )
{
for( i = 1; i < plot.np; i++ )
{
if( v[i-1] > midpoint && v[i] <= midpoint )
goto foundhl;
}
fprintf( stderr, "signal '%s' has no h->l transition\n", name );
return( NULL );
foundhl :
sig->hl_t = interp( midpoint, v[i-1], v[i], t[i-1], t[i] );
}
return( sig );
}
int find_delays()
{
Signal *vdd;
if( (timev = find( "time" )) == NULL )
{
fprintf( stderr, "variable 'time' missing\n" );
return( 0 );
}
if( (vdd = find( "vdd" )) == NULL )
{
fprintf( stderr, "variable 'vdd' missing\n" );
return( 0 );
}
midpoint = vdd->vals[0] / 2.0;
if( (in1 = FindTransitions( "in1", BOTH )) == NULL ) return( 0 );
if( (in2 = FindTransitions( "in2", L_H )) == NULL ) return( 0 );
if( (in3 = FindTransitions( "in3", H_L )) == NULL ) return( 0 );
if( (out1 = FindTransitions( "out1", BOTH )) == NULL ) return( 0 );
if( (out2 = FindTransitions( "out2", BOTH )) == NULL ) return( 0 );
if( (out3 = FindTransitions( "out3", L_H )) == NULL ) return( 0 );
if( (out4 = FindTransitions( "out4", H_L )) == NULL ) return( 0 );
out1->tphl = out1->hl_t - in1->lh_t;
out1->tplh = out1->lh_t - in1->hl_t;
out2->tphl = out2->hl_t - out1->lh_t;
out2->tplh = out2->lh_t - out1->hl_t;
out3->tplh = out3->lh_t - in2->lh_t;
out4->tphl = out4->hl_t - in3->hl_t;
return( 1 );
}
#define SQ( A ) ( (A) * (A) )
PrintResistEntries( cap, ns, ps )
double cap;
TranSz *ns, *ps;
{
double dyn_h, dyn_l, stat;
dyn_h = out3->tplh / cap;
dyn_l = out1->tphl / cap;
stat = ( SQ( out2->tphl ) - SQ( out1->tphl ) ) / (out1->tplh * cap );
PrintR( "n-channel", ns->w, ns->l, dyn_h, dyn_l, stat );
printf( "\n" );
dyn_h = out1->tplh / cap;
dyn_l = out4->tphl / cap;
stat = ( SQ( out2->tplh ) - SQ( out1->tplh ) ) / (out1->tphl * cap );
PrintR( "p-channel", ps->w, ps->l, dyn_h, dyn_l, stat );
}
#define round( A ) (int) ( (A) + 0.5 )
PrintR( ttype, w, l, rh, rl, rs )
char *ttype;
double w, l, rh, rl, rs;
{
static char *fmt = "resistance %s %s\t%.1f\t%.1f\t%d.0\n";
printf( fmt, ttype, "dynamic-high", w, l, round( rh ) );
printf( fmt, ttype, "dynamic-low\t", w, l, round( rl ) );
printf( fmt, ttype, "static\t", w, l, round( rs ) );
}